home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DJGOS106.ARJ / PAGING.C < prev    next >
C/C++ Source or Header  |  1992-04-13  |  18KB  |  710 lines

  1. /* This is file PAGING.C */
  2. /*
  3. ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* History:112,12 */
  17.  
  18. #include <dos.h>
  19. #include <fcntl.h>
  20. #include <io.h>
  21. #include <sys/stat.h>
  22.  
  23. #include "build.h"
  24. #include "types.h"
  25. #include "paging.h"
  26. #include "graphics.h"
  27. #include "tss.h"
  28. #include "idt.h"
  29. #include "gdt.h"
  30. #include "valloc.h"
  31. #include "dalloc.h"
  32. #include "utils.h"
  33. #include "aout.h"
  34. #include "mono.h"
  35. #include "vcpi.h"
  36.  
  37. #define VERBOSE 0
  38.  
  39.  
  40. #if DEBUGGER
  41. #define MAX_PAGING_NUM 1
  42. #else
  43. #define MAX_PAGING_NUM 4
  44. #endif
  45.  
  46.  
  47. #define    DOS_PAGE 256        /*  1MB / 4KB = 256 Pages  */
  48.  
  49.  
  50. extern word32 ptr2linear(void far *ptr);
  51.  
  52. CLIENT    client;        /*  VCPI Change Mode Structure  */
  53. word32    abs_client;    /*  _DS * 16L + &client        */
  54. far32    vcpi_entry;
  55. SYS_TBL    int_descriptor;
  56. SYS_TBL gbl_descriptor;
  57.  
  58. extern word16 vcpi_installed;    /*  VCPI Installed Flag  */
  59. extern near protect_entry();
  60.  
  61. extern TSS *utils_tss;
  62. extern int debug_mode;
  63. extern word16 mem_avail;
  64. extern int self_contained;
  65. extern long header_offset;
  66.  
  67. typedef struct AREAS {
  68.   word32 first_addr;
  69.   word32 last_addr;
  70.   word32 foffset; /* corresponding to first_addr; -1 = zero fill only */
  71.   } AREAS;
  72.  
  73. #define MAX_AREA    8
  74. static AREAS areas[MAX_AREA];
  75. static char *aname[MAX_AREA] = {
  76.     "text ",
  77.     "data ",
  78.     "bss  ",
  79.     "arena",
  80.     "stack",
  81.     "vga  ",
  82.     "syms ",
  83.     "emu"
  84. };
  85. static char achar[MAX_AREA] = "tdbmsg?e";
  86. typedef enum {
  87.   A_text,
  88.   A_data,
  89.   A_bss,
  90.   A_arena,
  91.   A_stack,
  92.   A_vga,
  93.   A_syms,
  94.   A_emu
  95. } AREA_TYPES;
  96.  
  97. static aout_f;
  98. static emu_f;
  99.  
  100. word32 far *pd = 0;
  101. word32 far *graphics_pt;
  102. extern word32 graphics_pt_lin;
  103. char paging_buffer[4096*MAX_PAGING_NUM];
  104.  
  105. /*  VCPI Get Interface  */
  106. void    link_vcpi(word32 far *dir, word32 far *table)
  107. {
  108.  
  109.   vcpi_entry.selector = g_vcpicode * 8;
  110.   vcpi_entry.offset32 = get_interface(table,&gdt[g_vcpicode]);
  111.   if (vcpi_entry.offset32 == -1L)
  112.     {
  113.     printf("CAUTION !!!!  This EMS driver used address 1B0000H.\n");
  114.     printf("This memory area is broken by handle_screen_swap().\n");
  115.     exit(1);
  116.     }
  117.  
  118.   int_descriptor.limit_16 = sizeof(idt);
  119.   int_descriptor.base_32  = ptr2linear(idt);
  120.   gbl_descriptor.limit_16 = sizeof(gdt);
  121.   gbl_descriptor.base_32  = ptr2linear(gdt);
  122.  
  123.   client.page_table   = (word32)dir>>12;
  124.   client.gdt_address  = ptr2linear(&gbl_descriptor);
  125.   client.idt_address  = ptr2linear(&int_descriptor);
  126.   client.ldt_selector = 0;
  127.   client.tss_selector = g_ctss * 8;
  128.   client.entry_eip    = (word16)protect_entry;
  129.   client.entry_cs     = g_rcode * 8;
  130.  
  131.   abs_client = ptr2linear(&client);
  132. }
  133.  
  134. handle_screen_swap(word32 far *pt)
  135. {
  136.   struct REGPACK r;
  137.   int have_mono=0;
  138.   int have_color=0;
  139.   int have_graphics=0;
  140.   int save, new, i;
  141.  
  142.   r.r_ax = 0x1200;
  143.   r.r_bx = 0xff10;
  144.   r.r_cx = 0xffff;
  145.   intr(0x10, &r);
  146.   if (r.r_cx == 0xffff)
  147.     pokeb(0x40, 0x84, 24); /* the only size for CGA/MDA */
  148.  
  149.   save = peekb(screen_seg, 0);
  150.   pokeb(screen_seg, 0, ~save);
  151.   new = peekb(screen_seg, 0);
  152.   pokeb(screen_seg, 0, save);
  153.   if (new == ~save)
  154.     have_color = 1;
  155.  
  156.   save = peekb(0xb000, 0);
  157.   pokeb(0xb000, 0, ~save);
  158.   new = peekb(0xb000, 0);
  159.   pokeb(0xb000, 0, save);
  160.   if (new == ~save)
  161.     have_mono = 1;
  162.  
  163.   r.r_ax = 0x0f00;
  164.   intr(0x10, &r);
  165.   if ((r.r_ax & 0xff) > 0x07)
  166.     have_graphics = 1;
  167.  
  168.   if (have_graphics && have_mono)
  169.     have_color = 1;
  170.   else if (have_graphics && have_color)
  171.     have_mono = 1;
  172.  
  173.   for (i=0; i<16; i++)
  174.     pt[0x1b0+i] = pt[0xb0+i];
  175.  
  176.   if (have_color && !have_mono)
  177.   {
  178.     for (i=0; i<8; i++)
  179.       pt[0x1b0+i] = pt[0xb8+i];
  180.     return;
  181.   }
  182.   if (have_mono & !have_color)
  183.   {
  184.     for (i=0; i<8; i++)
  185.       pt[0x1b8+i] = pt[0xb0+i];
  186.     return;
  187.   }
  188.  
  189.   if ((biosequip() & 0x0030) == 0x0030) /* mono mode, swap! */
  190.   {
  191.     for (i=0; i<8; i++)
  192.     {
  193.       pt[0x1b0+i] ^= pt[0x1b8+i];
  194.       pt[0x1b8+i] ^= pt[0x1b0+i];
  195.       pt[0x1b0+i] ^= pt[0x1b8+i];
  196.     }
  197.     return;
  198.   }
  199. }
  200.  
  201. paging_set_file(char *fname)
  202. {
  203.   word32 far *pt;
  204.   FILEHDR filehdr;
  205.   AOUTHDR aouthdr;
  206.   SCNHDR scnhdr[3];
  207.   GNU_AOUT gnu_aout;
  208.   int i;
  209.   aout_f = open(fname, O_RDONLY|O_BINARY);
  210.   if (aout_f < 0)
  211.   {
  212.     printf("Can't open file <%s>\n", fname);
  213.     exit(1);
  214.   }
  215.  
  216. #if TOPLINEINFO
  217.   for (i=0; fname[i]; i++)
  218.     poke(screen_seg, i*2+10, fname[i] | 0x0700);
  219. #endif
  220.  
  221.   lseek(aout_f, header_offset, 0);
  222.  
  223.   read(aout_f, &filehdr, sizeof(filehdr));
  224.   if (filehdr.f_magic != 0x14c)
  225.   {
  226.     lseek(aout_f, header_offset, 0);
  227.     read(aout_f, &gnu_aout, sizeof(gnu_aout));
  228.     a_tss.tss_eip = gnu_aout.entry;
  229.     aouthdr.tsize = gnu_aout.tsize;
  230.     aouthdr.dsize = gnu_aout.dsize;
  231.     aouthdr.bsize = gnu_aout.bsize;
  232.   }
  233.   else
  234.   {
  235.     read(aout_f, &aouthdr, sizeof(aouthdr));
  236.     a_tss.tss_eip = aouthdr.entry;
  237.     read(aout_f, scnhdr, sizeof(scnhdr));
  238.   }
  239.   a_tss.tss_cs = g_acode*8;
  240.   a_tss.tss_ds = g_adata*8;
  241.   a_tss.tss_es = g_adata*8;
  242.   a_tss.tss_fs = g_adata*8;
  243.   a_tss.tss_gs = g_adata*8;
  244.   a_tss.tss_ss = g_adata*8;
  245.   a_tss.tss_esp = 0x7ffffffc;
  246.  
  247.   if (filehdr.f_magic == 0x14c)
  248.   {
  249.     areas[0].first_addr = aouthdr.text_start + ARENA;
  250.     areas[0].foffset = scnhdr[0].s_scnptr + header_offset;
  251.     areas[0].last_addr = areas[0].first_addr + aouthdr.tsize;
  252.   }
  253.   else if (filehdr.f_magic == 0x10b)
  254.   {
  255.     areas[0].first_addr = ARENA;
  256.     if (a_tss.tss_eip >= 0x1000)    /* leave space for null reference */
  257.       areas[0].first_addr += 0x1000;    /* to cause seg fault */
  258.     areas[0].foffset = header_offset;
  259.     areas[0].last_addr = areas[0].first_addr + aouthdr.tsize + 0x20;
  260.   }
  261. #if DEBUGGER
  262.   else if (filehdr.f_magic == 0x107)
  263.   {
  264.     struct stat sbuf;
  265.     fstat(aout_f, &sbuf);
  266.     areas[0].first_addr = ARENA;
  267.     areas[0].foffset = 0x20 + header_offset;
  268.     areas[0].last_addr = sbuf.st_size + ARENA - 0x20;
  269.   }
  270.   else
  271.   {
  272.     struct stat sbuf;
  273.     fstat(aout_f, &sbuf);
  274.     areas[0].first_addr = ARENA;
  275.     areas[0].foffset = header_offset;
  276.     areas[0].last_addr = sbuf.st_size + ARENA;
  277.   }
  278. #else
  279.   else
  280.   {
  281.     printf("Unknown file type 0x%x (0%o)\n", filehdr.f_magic, filehdr.f_magic);
  282.     exit(-1);
  283.   }
  284. #endif
  285. #if DEBUGGER
  286.   if (debug_mode)
  287.     printf("%ld+", aouthdr.tsize);
  288. #endif
  289.  
  290.   if (filehdr.f_magic == 0x14c)
  291.   {
  292.     areas[1].first_addr = aouthdr.data_start + ARENA;
  293.     areas[1].foffset = scnhdr[1].s_scnptr + header_offset;
  294.   }
  295.   else
  296.   {
  297.     areas[1].first_addr = (areas[0].last_addr+0x3fffffL)&~0x3fffffL;
  298.     areas[1].foffset = ((aouthdr.tsize + 0x20 + 0xfffL) & ~0xfffL) + header_offset;
  299.   }
  300.   areas[1].last_addr = areas[1].first_addr + aouthdr.dsize - 1;
  301. #if DEBUGGER
  302.   if (debug_mode)
  303.     printf("%ld+", aouthdr.dsize);
  304. #endif
  305.  
  306.   areas[2].first_addr = areas[1].last_addr + 1;
  307.   areas[2].foffset = -1;
  308.   areas[2].last_addr = areas[2].first_addr + aouthdr.bsize - 1;
  309. #if DEBUGGER
  310.   if (debug_mode)
  311.     printf("%ld = %ld\n", aouthdr.bsize,
  312.       aouthdr.tsize+aouthdr.dsize+aouthdr.bsize);
  313. #endif
  314.  
  315.   areas[3].first_addr = areas[2].last_addr;
  316.   areas[3].last_addr = areas[3].first_addr;
  317.   areas[3].foffset = -1;
  318.  
  319.   areas[4].first_addr = 0x50000000;
  320.   areas[4].last_addr = 0x8fffffff;
  321.   areas[4].foffset = -1;
  322.  
  323.   areas[5].first_addr = 0xe0000000;
  324.   areas[5].last_addr = 0xe03fffff;
  325.   areas[5].foffset = -1;
  326.  
  327.   areas[A_syms].first_addr = 0xa0000000;
  328.   areas[A_syms].last_addr = 0xafffffff;
  329.   areas[A_syms].foffset = -1;
  330.  
  331.   pd = (word32 far *)((long)valloc(VA_640) << 24);
  332.   pt = (word32 far *)((long)valloc(VA_640) << 24);
  333.   for (i=0; i<1024; i++)
  334.     pd[i] = 0;
  335.  
  336.   if (vcpi_installed)
  337.     {
  338.     link_vcpi(pd,pt);        /*  Get VCPI Page Table  */
  339.     for ( i=0; i<1024; i++)
  340.       if (pt[i] & PT_P)
  341.     pt[i] |= PT_I;
  342.     }
  343.   else
  344.     {
  345.     for (i=0; i < DOS_PAGE; i++)
  346.       pt[i] = ((unsigned long)i<<12) | PT_P | PT_W | PT_I;
  347.     for (; i<1024; i++)
  348.       pt[i] = 0;
  349.     }
  350.  
  351.   pd[0] = ((word32)pt >> 12) | PT_P | PT_W | PT_I;    /* map 0-1M 1:1 */
  352.   pd[0x3c0] = ((word32)pt >> 12) | PT_P | PT_W | PT_I;    /* map also to 0xF0000000 */
  353.   handle_screen_swap(pt);
  354.  
  355.   graphics_pt = (word32 far *)((long)valloc(VA_640) << 24);
  356.   graphics_pt_lin = ptr2linear(graphics_pt);
  357.   for (i=0; i<1024; i++)
  358.     graphics_pt[i] = 0x000a0000L | ((i * 4096L) & 0xffffL) | PT_W | PT_U;
  359.   pd[0x380] = ((word32)graphics_pt >> 12) | PT_P | PT_W | PT_U;
  360.  
  361.   c_tss.tss_cr3 = (unsigned long)pd >> 12;
  362.   a_tss.tss_cr3 = (unsigned long)pd >> 12;
  363.   o_tss.tss_cr3 = (unsigned long)pd >> 12;
  364.   i_tss.tss_cr3 = (unsigned long)pd >> 12;
  365.   p_tss.tss_cr3 = (unsigned long)pd >> 12;
  366.   f_tss.tss_cr3 = (unsigned long)pd >> 12;
  367.   v74_tss.tss_cr3 = (unsigned long)pd >> 12;
  368.   v78_tss.tss_cr3 = (unsigned long)pd >> 12;
  369.   v79_tss.tss_cr3 = (unsigned long)pd >> 12;
  370.  
  371. #if VERBOSE
  372.     for (i=0; i<5; i++)
  373.       printf("%d %-10s %08lx-%08lx (offset 0x%08lx)\n", i, aname[i], areas[i].first_addr, areas[i].last_addr, areas[i].foffset);
  374. #endif
  375. }
  376.  
  377. #if TOPLINEINFO
  378. static update_status(int c, int col)
  379. {
  380.   int r;
  381.   r = peek(screen_seg, 2*79);
  382.   poke(screen_seg, 2*col, c);
  383.   return r;
  384. }
  385. #endif
  386.  
  387. word32 paging_brk(word32 b)
  388. {
  389.   word32 r = (areas[3].last_addr - ARENA + 7) & ~7;
  390.   areas[3].last_addr = b + ARENA;
  391.   return r;
  392. }
  393.  
  394. word32 paging_sbrk(int32 b)
  395. {
  396.   word32 r = (areas[3].last_addr - ARENA + 7) & ~7;
  397.   areas[3].last_addr = r + b + ARENA;
  398.   return r;
  399. }
  400.  
  401. page_is_valid(word32 vaddr)
  402. {
  403.   int a;
  404.   for (a=0; a<MAX_AREA; a++)
  405.     if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
  406.       return 1;
  407.   if (vaddr >= 0xf000000L)
  408.     return 1;
  409.   return 0;
  410. }
  411.  
  412. page_in()
  413. {
  414.   int old_status;
  415.   TSS *old_util_tss;
  416.   word32 far *pt;
  417.   word32 far *p;
  418.   word32 vaddr, foffset, cnt32;
  419.   word32 eaddr, vtran, vcnt, zaddr;
  420.   int pdi, pti, pn, a, cnt, count;
  421.   unsigned dblock;
  422.  
  423. #if 0
  424.   unsigned char buf[100];
  425.   sprintf(buf, "0x%08lx", a_tss.tss_cr2 - ARENA);
  426.   for (a=0; buf[a]; a++)
  427.     poke(screen_seg, 80+a*2, 0x0600 | buf[a]);
  428. #endif
  429.  
  430.   old_util_tss = utils_tss;
  431.   utils_tss = &f_tss;
  432.   vaddr = tss_ptr->tss_cr2;
  433.  
  434.   for (a=0; a<MAX_AREA; a++)
  435.     if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
  436.       goto got_area;
  437.  
  438.   printf("Segmentation violation in pointer 0x%08lx at %x:%lx\n",
  439.    tss_ptr->tss_cr2-ARENA, tss_ptr->tss_cs, tss_ptr->tss_eip);
  440.   return 1;
  441.  
  442. got_area:
  443.   vaddr &= 0xFFFFF000;    /* points to beginning of page */
  444. #if 0 /* handled in protected mode for speed */
  445.   if (a == A_vga)
  446.     return graphics_fault(vaddr, graphics_pt);
  447. #endif
  448.  
  449. #if VERBOSE
  450.     printf("area(%d) - ", a);
  451. #endif
  452.  
  453.   if ((a == 2) & (vaddr < areas[a].first_addr)) /* bss, but data too */
  454.   {
  455. #if VERBOSE
  456.       printf("split page (data/bss) detected - ");
  457. #endif
  458.     a = 1; /* set to page in data */
  459.   }
  460.  
  461. #if TOPLINEINFO
  462.   old_status = update_status(achar[a] | 0x0a00, 78);
  463. #endif
  464. #if VERBOSE
  465.   printf("Paging in %s block for vaddr %#010lx -", aname[a], tss_ptr->tss_cr2-ARENA);
  466. #endif
  467.   pdi = (vaddr >> 22) & 0x3ff;
  468.   if (!(pd[pdi] & PT_P))    /* put in an empty page table if required */
  469.   {
  470.     pn = valloc(VA_640);
  471.     pt = (word32 far *)((word32)pn << 24);
  472.     pd[pdi] = ((word32)pn<<12) | PT_P | PT_W | PT_I | PT_S;
  473.     for (pti=0; pti<1024; pti++)
  474.       pt[pti] = PT_W | PT_S;
  475.   }
  476.   else
  477.     pt = (word32 far *)((pd[pdi]&~0xFFF) << 12);
  478.   pti = (vaddr >> 12) & 0x3ff;
  479.   if (pt[pti] & PT_P)
  480.   {
  481.     utils_tss = old_util_tss;
  482. #if TOPLINEINFO
  483.     update_status(old_status, 78);
  484. #endif
  485.     return 0;
  486.   }
  487.   count = MAX_PAGING_NUM;
  488.   if (count > mem_avail/4)
  489.     count = mem_avail/4;
  490.   if (pti + count > 1024)
  491.     count = 1024 - pti;
  492.   if (vaddr + count*4096L > areas[a].last_addr+4096L)
  493.     count = (areas[a].last_addr - vaddr + 4095) / 4096;
  494.   if (count < 1)
  495.     count = 1;
  496.   zaddr = eaddr = -1;
  497.   vtran = vaddr;
  498.   vcnt = 0;
  499.   for (; count; count--, pti++, vaddr+=4096)
  500.   {
  501.     if (pt[pti] & PT_P)
  502.       break;
  503.     dblock = pt[pti] >> 12;
  504.     pn = valloc(VA_1M);
  505.     pt[pti] &= 0xfffL & ~(word32)(PT_A | PT_D | PT_C);
  506.     pt[pti] |= ((word32)pn << 12) | PT_P;
  507.  
  508.     if (pt[pti] & PT_I)
  509.     {
  510. #if VERBOSE
  511.         printf(" swap");
  512. #endif
  513.       dread(paging_buffer, dblock);
  514.       dfree(dblock);
  515.       memput(vaddr, paging_buffer, 4096);
  516.     }
  517.     else
  518.     {
  519.       if (areas[a].foffset != -1)
  520.       {
  521. #if VERBOSE
  522.         if (a == A_emu)
  523.           printf(" emu");
  524.         else
  525.           printf(" exec");
  526. #endif
  527.         if (eaddr == -1)
  528.         {
  529.           eaddr = areas[a].foffset + (vaddr - areas[a].first_addr);
  530.           vtran = vaddr;
  531.         }
  532.         cnt32 = areas[a].last_addr - vaddr + 1;
  533.         if (cnt32 > 4096)
  534.           cnt32 = 4096;
  535.         else
  536.           zaddr = vaddr;
  537.         vcnt += cnt32;
  538.       }
  539.       else
  540.       {
  541.         zero32(vaddr);
  542. #if VERBOSE
  543.         printf(" zero");
  544. #endif
  545.       }
  546.       pt[pti] |= PT_I;
  547.     }
  548.   }
  549.   if (eaddr != -1)
  550.   {
  551.     int cur_f, rsize;
  552.     if (a == A_emu)
  553.       cur_f = emu_f;
  554.     else
  555.       cur_f = aout_f;
  556.     lseek(cur_f, eaddr, 0);
  557.     rsize = read(cur_f, paging_buffer, vcnt);
  558.     if (rsize < vcnt)
  559.       memset(paging_buffer+rsize, 0, vcnt-rsize);
  560.     if (zaddr != -1)
  561.       zero32(zaddr);
  562.     memput(vtran, paging_buffer, vcnt);
  563.   }
  564. #if VERBOSE
  565.   printf("\n");
  566. #endif
  567.   utils_tss = old_util_tss;
  568. #if TOPLINEINFO
  569.   update_status(old_status, 78);
  570. #endif
  571.   return 0;
  572. }
  573.  
  574. static last_po_pdi = 0;
  575. static last_po_pti = 0;
  576.  
  577. unsigned page_out(int where) /* return >= 0 page which is paged out, 0xffff if not */
  578. {
  579.   int start_pdi, start_pti, old_status;
  580.   word32 far *pt, v;
  581.   unsigned dblock, pn;
  582. #if TOPLINEINFO
  583.   old_status = update_status('>' | 0x0a00, 79);
  584. #endif
  585.   start_pdi = last_po_pdi;
  586.   start_pti = last_po_pti;
  587.   pt = (word32 far *)((pd[last_po_pdi]&~0xFFF) << 12);
  588.   do {
  589.     if ((pd[last_po_pdi] & (PT_P | PT_S)) == (PT_P | PT_S))
  590.     {
  591.       if ((pt[last_po_pti] & (PT_P | PT_S)) == (PT_P | PT_S))
  592.       {
  593.         pn = pt[last_po_pti] >> 12;
  594.         switch (where) {
  595.         case VA_640:
  596.           if (pn < DOS_PAGE) goto swapout;
  597.           break;
  598.         case VA_1M:
  599.           if (pn >= DOS_PAGE) goto swapout;
  600.           break;
  601.         default:
  602.           swapout:
  603.             dblock = dalloc();
  604.             v = ((word32)last_po_pdi << 22) | ((word32)last_po_pti << 12);
  605.             memget(v, paging_buffer, 4096);
  606.             dwrite(paging_buffer, dblock);
  607. #if VERBOSE
  608.             printf ("out %d:%d", last_po_pdi, last_po_pti);
  609. #endif
  610.             pt[last_po_pti] &= 0xfff & ~PT_P; /* no longer present */
  611.             pt[last_po_pti] |= (long)dblock << 12;
  612. #if TOPLINEINFO
  613.             update_status(old_status, 79);
  614. #endif
  615.             return pn;
  616.         }
  617.       }
  618.     }
  619.     else /* imagine we just checked the last entry */
  620.       last_po_pti = 1023;
  621.     if (++last_po_pti == 1024)
  622.     {
  623.       last_po_pti = 0;
  624.       if (++last_po_pdi == 1024)
  625.         last_po_pdi = 0;
  626.       pt = (word32 far *)((pd[last_po_pdi]&~0xFFF) << 12);
  627.     }
  628.   } while ((start_pdi != last_po_pdi) || (start_pti != last_po_pti));
  629. #if TOPLINEINFO
  630.   update_status(old_status, 79);
  631. #endif
  632.   return 0xffff;
  633. }
  634.  
  635. unsigned pd_dblock;
  636.  
  637. page_out_everything()
  638. {
  639.   int pdi;
  640.   unsigned pn;
  641.   unsigned ptb;
  642.   void far *fp;
  643.   while ((pn = page_out(-1)) != 0xffff) vfree(pn);
  644.   for (pdi=0; pdi<1024; pdi++)
  645.     if (pd[pdi])
  646.     {
  647.       ptb = dalloc();
  648.       fp = (void far *)((pd[pdi]&~0xFFF)<<12);
  649.       movedata(FP_SEG(fp), FP_OFF(fp), _DS, paging_buffer, 4096);
  650.       dwrite(paging_buffer, ptb);
  651.       vfree(pd[pdi]>>12);
  652.       pd[pdi] = (pd[pdi] & (0xFFF&~PT_P)) | ((word32)ptb<<12);
  653.     }
  654.   movedata(FP_SEG(pd), FP_OFF(pd), _DS, paging_buffer, 4096);
  655.   pd_dblock = dalloc();
  656.   dwrite(paging_buffer, pd_dblock);
  657.   vfree(((word32)pd)>>24);
  658.   xms_free();
  659. }
  660.  
  661. extern int valloc_initted;
  662.  
  663. page_in_everything()
  664. {
  665.   int pdi;
  666.   unsigned ptb;
  667.   word32 far *pt;
  668.   unsigned pta;
  669.   valloc_initted = 0;
  670.   pta = valloc(VA_640);
  671.   pd = (word32 far *)((word32)pta << 24);
  672.   dread(paging_buffer, pd_dblock);
  673.   dfree(pd_dblock);
  674.   movedata(_DS, paging_buffer, FP_SEG(pd), FP_OFF(pd), 4096);
  675.   for (pdi=0; pdi<1024; pdi++)
  676.     if (pd[pdi])
  677.     {
  678.       pta = valloc(VA_640);
  679.       pt = (word32 far *)((word32)pta << 24);
  680.       ptb = pd[pdi] >> 12;
  681.       dread(paging_buffer, ptb);
  682.       dfree(ptb);
  683.       movedata(_DS, paging_buffer, FP_SEG(pt), FP_OFF(pt), 4096);
  684.       pd[pdi] = (pd[pdi] & 0xFFF) | ((word32)pta<<12) | PT_P;
  685.     }
  686.   graphics_pt = (word32 far *)((pd[0x380]&~0xfff) << 12);
  687.   graphics_pt_lin = ptr2linear(graphics_pt);
  688. }
  689.  
  690.  
  691. int emu_install(char *filename)
  692. {
  693.   GNU_AOUT eh;
  694.   areas[A_emu].first_addr = EMU_TEXT+ARENA;
  695.   areas[A_emu].last_addr = EMU_TEXT-1+ARENA;
  696.   areas[A_emu].foffset = 0;
  697.  
  698.   if (filename == 0)
  699.     return 0;
  700.   emu_f = open(filename, O_RDONLY|O_BINARY);
  701.   if (emu_f < 0)
  702.   {
  703.     printf("Can't open 80387 emulator file <%s>\n", filename);
  704.     return 0;
  705.   }
  706.   read(emu_f, &eh, sizeof(eh));
  707.   areas[A_emu].last_addr += eh.tsize + eh.dsize + eh.bsize + 0x20;
  708.   return 1;
  709. }
  710.